#! #! /usr/bin/python
# 分析各个部件下的 BUILD.gn 内使用依赖部件的情况

from genericpath import isdir
import os
import json

ohos_root = r"/home/cyd/ohos"
script_dir = ""
cur_path = ""
# warning_count = 0

def get_all_paths() -> list:
    '''
    @func: 打开文件 part_list.txt 获取所有的部件的相对路径。
    @note: part_list.txt 通过脚本 find-all-part.py 生成。 
    '''
    f = open("part_list.txt", 'r')
    list_paths = []
    for line in f:
       list_paths.append(line.strip('\n')) 
    f.close()
    return list_paths

def get_gni_path(line:str) -> str:
    return line.split('"')[1]

def isPath(path:str) -> bool:
    '''
    @func: 判断 path 是否为一个目录路径
    @note: 以 '/' 开头且只含有一个，判断为非路径
    '''
    if path[0] == '/' and path.count('/') == 1:
        return False
    else:
        return True

def get_out_path(line:str) -> str:
    path = line.split('"')[1] # 暂不考虑一行有两个路径的可能性
    if (len(path) <= 1): # 考虑 "", "/" 的情况
        return ""
    elif path[:3] != '../' and path[0] != '/': # 不以 / 开头的字符串都不认为是可疑路径（忽略变量，相对路径）
        return ""
    elif '//third_party' in path:
        return ""
    # else:
    #     if ':' in path: # 截取 dep 前半段部分(不需要)
    #         path = path.split(':')[0]
    # 仍有可能不是路径，比如一些 flag 字段
    elif path[0] == '/' and path.count('/') == 1:
        return ""
    elif path[0] == '/' and path[1] != '/':
        return ""
    return path

def is_sub_path(gn_path:str, in_path:str) -> bool:
    '''
    @var:   gn_path:   gn 文件的路径
            in_path:   gn 文件内包含的路径
    @func: gn 文件内包含的路径是否为 part_path 的子目录。
    @note:
      1. in_path 可能为 '../' 形式的相对路径
      2. in_path 末尾可能包含 ':' 号
      3. in_path/gn_path 可能是文件名 
      4. gn_path 与 in_path 拼接后的目录, 只要在当前目录（部件的根目录）下就说明为子目录
    '''
    if ':' in in_path:
        in_path = in_path.split(':')[0]
    in_path = os.path.dirname(in_path)
    gn_path = os.path.dirname(gn_path)
    path_of_gn = gn_path + '/' + in_path
    path_of_gn = os.path.normpath(path_of_gn)
    if path_of_gn[:2] == '..':
        return False
    else:
        return True

def analyze_gn(gn_path) -> dict:
    '''
    @func: 分析单个 BUILD.gn 文件
    '''
    # global warning_count
    gni_file_list = [] # 暂不处理 import 的 gni 文件
    out_path = [] # gn 文件内的可疑路径
    gn_warning_dict = {}
    # print(gn_path) # test
    with open(gn_path, 'r', encoding='utf-8') as f:
        line_number = 0 # 行号
        gn_path = os.path.normpath(gn_path) # 标准化路径
        for line in f:
            line_number += 1
            gn_line = line.strip()
            if len(gn_line) == 0 or gn_line[0] == '#':
                continue
            if '.gni' in gn_line:
                gni_file_list += get_gni_path(gn_line)
                continue
            if '/' in gn_line and '"' in gn_line: # 可能含有路径的行
                temp_path = get_out_path(gn_line) # 包含 ../ 形式路径
                if not temp_path:
                    continue
                if temp_path[0] == '/': # "//" 形式路径
                    out_path.append(str(line_number) + ":  " + temp_path) # 带行号
                    # warning_count += 1
                elif not is_sub_path(gn_path, temp_path): # "../" 形式路径
                    out_path.append(str(line_number) + ":  " + temp_path)
                    # warning_count += 1
    if out_path:
        gn_warning_dict[gn_path] = out_path
    return gn_warning_dict

def analyze_part(part_path) -> list:
    origin_path = os.getcwd()
    try:
        os.chdir(part_path)
    except FileNotFoundError as e:
        print('Error: segment path error: ' + part_path)
        return
    part_warning_list = []
    gn_file_list = os.popen('find . -name *.gn')
    for i in gn_file_list:
        temp_dict = analyze_gn(i.strip('\n'))
        if temp_dict:
            part_warning_list.append(temp_dict)
    os.chdir(origin_path)
    return part_warning_list

def analyze_all_parts(all_parts) -> dict:
    parts_dict = {}
    for i in all_parts:
        part_warning_list = analyze_part(i)
        if part_warning_list:
            parts_dict[i] = part_warning_list
    with open('all_part_warning.json', 'w') as f:
        f.write(json.dumps(parts_dict, indent=4))


if __name__ == '__main__':
    script_dir = os.getcwd()
    os.chdir(ohos_root)
    all_parts = get_all_paths()
    analyze_all_parts(all_parts)
    # print(warning_count) # test